﻿using System;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.IO.IsolatedStorage;
using System.Xml.Serialization;
using System.Data;

namespace Light.Utility
{
    /// <summary>
    /// 文件操作类
    /// </summary>
    public class FileHelper //: IDataExport, IDataImport
    {
        public static void ClearIsolatedStorage(string dir, IsolatedType isoType)
        {
            if (!string.IsNullOrEmpty(dir))
            {
                using (IsolatedStorageFile file = GetIsolatedStorageFile(isoType))
                {
                    string[] fileNames = file.GetFileNames(dir + @"\*");
                    if (fileNames.Length > 0)
                    {
                        for (int i = 0; i < fileNames.Length; i++)
                        {
                            file.DeleteFile(dir + @"\" + fileNames[i]);
                        }
                    }
                    file.Close();
                }
            }
        }

        public void Export(DataSet data, string fileName, DataFileType dataFileType)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (fileName == null)
            {
                throw new ArgumentNullException("fileName");
            }
            if (fileName.Length == 0)
            {
                throw new ArgumentException("fileName");
            }
            FileInfo info = new FileInfo(fileName);
            if (dataFileType == DataFileType.Auto)
            {
                dataFileType = this.GetDataFileType(info.FullName);
            }
            switch (dataFileType)
            {
                case DataFileType.XML:
                    this.ExportToXML(data, info.FullName);
                    break;

                case DataFileType.XML_EXCEL:
                    this.ExportToXmlExcel(data, info.FullName);
                    break;

                case DataFileType.EXCEL:
                    this.ExportToExcel(data, info.FullName);
                    break;

                case DataFileType.TEXT:
                    this.ExportToText(data, info.FullName, '\t');
                    break;

                case DataFileType.CSV:
                    this.ExportToText(data, info.FullName, ',');
                    break;

                default:
                    throw new NotSupportedException();
            }
        }

        public void Export(DataTable data, string fileName, DataFileType dataFileType)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (fileName == null)
            {
                throw new ArgumentNullException("fileName");
            }
            if (fileName.Length == 0)
            {
                throw new ArgumentException("fileName");
            }
            if (data.Columns.Count != 0)
            {
                string dataSetName = null;
                if (data.DataSet != null)
                {
                    dataSetName = data.DataSet.DataSetName;
                }
                else
                {
                    dataSetName = data.TableName + "_Data";
                }
                DataTable table = data.Copy();
                DataSet set = new DataSet(dataSetName);
                set.Tables.Add(table);
                set.AcceptChanges();
                this.Export(set, fileName, dataFileType);
            }
        }

        private void ExportToExcel(DataSet data, string fileName)
        {
            using (ExcelReader reader = new ExcelReader(fileName))
            {
                reader.Headers = true;
                reader.MixedData = false;
                reader.Open();
                try
                {
                    foreach (DataTable table in data.Tables)
                    {
                        reader.WriteData(table);
                    }
                }
                finally
                {
                    reader.Close();
                }
            }
        }

        private void ExportToText(DataSet data, string fileName, char separator)
        {
            bool aNSI = separator == ',';
            for (int i = 0; i < data.Tables.Count; i++)
            {
                DataTable table = data.Tables[i];
                string path = fileName;
                if (data.Tables.Count > 1)
                {
                    string directoryName = Path.GetDirectoryName(fileName);
                    string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
                    string extension = Path.GetExtension(fileName);
                    path = directoryName + @"\" + fileNameWithoutExtension + "[" + table.TableName + "]" + extension;
                }
                StreamWriter sw = null;
                if (aNSI)
                {
                    sw = new StreamWriter(fileName, false, Encoding.Default);
                }
                else
                {
                    sw = File.CreateText(path);
                }
                using (sw)
                {
                    try
                    {
                        StringBuilder builder = new StringBuilder();
                        for (int j = 0; j < table.Columns.Count; j++)
                        {
                            builder.Append(table.Columns[j].ColumnName);
                            if (j < (table.Columns.Count - 1))
                            {
                                builder.Append(separator);
                            }
                        }
                        this.WriteTextLine(sw, builder.ToString(), aNSI);
                        for (int k = 0; k < table.Rows.Count; k++)
                        {
                            builder = new StringBuilder();
                            DataRow row = table.Rows[k];
                            for (int m = 0; m < table.Columns.Count; m++)
                            {
                                if ((row[m] != null) && (row[m] != DBNull.Value))
                                {
                                    builder.Append(row[m].ToString());
                                }
                                else
                                {
                                    builder.Append(string.Empty);
                                }
                                if (m < (table.Columns.Count - 1))
                                {
                                    builder.Append(separator);
                                }
                            }
                            this.WriteTextLine(sw, builder.ToString(), aNSI);
                        }
                        sw.Flush();
                    }
                    finally
                    {
                        sw.Close();
                    }
                }
            }
        }

        private void ExportToXML(DataSet data, string fileName)
        {
            data.WriteXml(fileName, XmlWriteMode.WriteSchema);
        }

        private void ExportToXmlExcel(DataSet data, string fileName)
        {
            using (StreamWriter writer = new StreamWriter(fileName))
            {
                try
                {
                    writer.Write("<?xml version=\"1.0\"?>\r\n<?mso-application progid=\"Excel.Sheet\"?>\r\n<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\r\n xmlns:o=\"urn:schemas-microsoft-com:office:office\"\r\n xmlns:x=\"urn:schemas-microsoft-com:office:excel\"\r\n xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"\r\nxmlns:html=\"http://www.w3.org/TR/REC-html40\">\r\n<DocumentProperties xmlns=\"urn:schemas-microsoft-com:office:office\">\r\n<Version>11.6360</Version>\r\n</DocumentProperties>\r\n<Styles>\r\n <Style ss:ID=\"Default\" ss:Name=\"Normal\">\r\n <Alignment ss:Vertical=\"Bottom\"/>\r\n <Borders/>\r\n <Font/>\r\n <Interior/>\r\n <NumberFormat/>\r\n <Protection/>\r\n </Style>\r\n <Style ss:ID=\"BoldColumn\">\r\n <Font x:Family=\"Swiss\" ss:Bold=\"1\"/>\r\n </Style>\r\n <Style     ss:ID=\"StringLiteral\">\r\n <NumberFormat ss:Format=\"@\"/>\r\n </Style>\r\n <Style ss:ID=\"Decimal\">\r\n <NumberFormat ss:Format=\"0.0000\"/>\r\n </Style>\r\n <Style ss:ID=\"Integer\">\r\n <NumberFormat ss:Format=\"0\"/>\r\n </Style>\r\n <Style ss:ID=\"DateLiteral\">\r\n <NumberFormat ss:Format=\"mm/dd/yyyy;@\"/>\r\n </Style>\r\n </Styles>\r\n ");
                    for (int i = 0; i < data.Tables.Count; i++)
                    {
                        writer.Write("<Worksheet ss:Name=\"" + data.Tables[i].TableName + "\">");
                        writer.Write("<Table>");
                        writer.Write("<Row>");
                        for (int j = 0; j < data.Tables[i].Columns.Count; j++)
                        {
                            writer.Write("<Cell ss:StyleID=\"BoldColumn\"><Data ss:Type=\"String\">");
                            writer.Write(data.Tables[i].Columns[j].ColumnName);
                            writer.Write("</Data></Cell>");
                        }
                        writer.Write("</Row>");
                        int num3 = 0;
                        foreach (DataRow row in data.Tables[i].Rows)
                        {
                            num3++;
                            if (num3 != 0xfa00)
                            {
                                writer.Write("<Row>");
                                for (int k = 0; k < data.Tables[i].Columns.Count; k++)
                                {
                                    Type type = row[k].GetType();
                                    switch (type.ToString())
                                    {
                                        case "System.String":
                                            {
                                                string str = row[k].ToString().Trim().Replace("&", "&amp;").Replace(">", ">").Replace("<", "<");
                                                writer.Write("<Cell ss:StyleID=\"StringLiteral\"><Data ss:Type=\"String\">");
                                                writer.Write(str);
                                                writer.Write("</Data></Cell>");
                                                break;
                                            }
                                        case "System.DateTime":
                                            {
                                                DateTime time = (DateTime)row[k];
                                                string str2 = "";
                                                string[] strArray = new string[12];
                                                int year = time.Year;
                                                strArray[0] = year.ToString();
                                                strArray[1] = "-";
                                                strArray[2] = (time.Month < 10) ? ("0" + (year = time.Month).ToString()) : (year = time.Month).ToString();
                                                strArray[3] = "-";
                                                strArray[4] = (time.Day < 10) ? ("0" + (year = time.Day).ToString()) : (year = time.Day).ToString();
                                                strArray[5] = "T";
                                                strArray[6] = (time.Hour < 10) ? ("0" + (year = time.Hour).ToString()) : (year = time.Hour).ToString();
                                                strArray[7] = ":";
                                                strArray[8] = (time.Minute < 10) ? ("0" + (year = time.Minute).ToString()) : (year = time.Minute).ToString();
                                                strArray[9] = ":";
                                                strArray[10] = (time.Second < 10) ? ("0" + (year = time.Second).ToString()) : (year = time.Second).ToString();
                                                strArray[11] = ".000";
                                                str2 = string.Concat(strArray);
                                                writer.Write("<Cell ss:StyleID=\"DateLiteral\"><Data ss:Type=\"DateTime\">");
                                                writer.Write(str2);
                                                writer.Write("</Data></Cell>");
                                                break;
                                            }
                                        case "System.Boolean":
                                            writer.Write("<Cell ss:StyleID=\"StringLiteral\"><Data ss:Type=\"String\">");
                                            writer.Write(row[k].ToString());
                                            writer.Write("</Data></Cell>");
                                            break;

                                        case "System.Int16":
                                        case "System.Int32":
                                        case "System.Int64":
                                        case "System.Byte":
                                        case "System.SByte":
                                            writer.Write("<Cell ss:StyleID=\"Integer\"><Data ss:Type=\"Number\">");
                                            writer.Write(row[k].ToString());
                                            writer.Write("</Data></Cell>");
                                            break;

                                        case "System.Decimal":
                                        case "System.Double":
                                            writer.Write("<Cell ss:StyleID=\"Decimal\"><Data ss:Type=\"Number\">");
                                            writer.Write(row[k].ToString());
                                            writer.Write("</Data></Cell>");
                                            break;

                                        case "System.DBNull":
                                            writer.Write("<Cell ss:StyleID=\"StringLiteral\"><Data ss:Type=\"String\">");
                                            writer.Write("");
                                            writer.Write("</Data></Cell>");
                                            break;

                                        default:
                                            throw new Exception(type.ToString() + " not handled.");
                                    }
                                }
                                writer.Write("</Row>");
                            }
                        }
                        writer.Write("</Table>");
                        writer.Write(" </Worksheet>");
                    }
                    writer.Write("</Workbook>");
                    writer.Flush();
                }
                finally
                {
                    writer.Close();
                }
            }
        }

        public static object FileExtractObject(string fileName, Type type)
        {
            if (string.IsNullOrEmpty(fileName))
            {
                throw new ArgumentException("fileName");
            }
            object obj2 = null;
            try
            {
                using (FileStream stream = new FileStream(fileName, FileMode.Open))
                {
                    obj2 = new XmlSerializer(type).Deserialize(stream);
                    stream.Close();
                }
            }
            catch (Exception exception)
            {
                Trace.WriteLine(exception);
                obj2 = Activator.CreateInstance(type, true);
            }
            return obj2;
        }

        public static void FileStorageObject(string fileName, object obj)
        {
            if (string.IsNullOrEmpty(fileName))
            {
                throw new ArgumentException("fileName");
            }
            try
            {
                using (TextWriter writer = new StreamWriter(fileName))
                {
                    new XmlSerializer(obj.GetType()).Serialize(writer, obj);
                    writer.Close();
                }
            }
            catch (Exception exception)
            {
                Trace.WriteLine(exception);
            }
        }

        private DataFileType GetDataFileType(string fileName)
        {
            if (fileName == null)
            {
                throw new ArgumentNullException("fileName");
            }
            if (!Path.HasExtension(fileName))
            {
                throw new ArgumentException("fileName");
            }
            switch (Path.GetExtension(fileName).ToLower())
            {
                case ".xml":
                    return DataFileType.XML;

                case ".txt":
                case ".text":
                    return DataFileType.TEXT;

                case ".csv":
                    return DataFileType.CSV;

                case ".xls":
                case ".xlsx":
                    return DataFileType.EXCEL;

                case ".htm":
                case ".html":
                    return DataFileType.HTML;
            }
            throw new NotSupportedException();
        }

        public static IsolatedStorageFile GetIsolatedStorageFile(IsolatedType isoType)
        {
            if (isoType == IsolatedType.Domain)
            {
                return IsolatedStorageFile.GetUserStoreForDomain();
            }
            return IsolatedStorageFile.GetUserStoreForAssembly();
        }

        public static IsolatedStorageFileStream GetIsolatedStorageFileStream(string fileName, FileMode mode, IsolatedType isoType)
        {
            if (string.IsNullOrEmpty(fileName))
            {
                throw new ArgumentException("fileName");
            }
            return new IsolatedStorageFileStream(fileName, mode, GetIsolatedStorageFile(isoType));
        }

        public static bool HasIsolatedDirectory(string directoryName, IsolatedType isoType)
        {
            bool flag;
            if (string.IsNullOrEmpty(directoryName))
            {
                return false;
            }
            IsolatedStorageFile isolatedStorageFile = GetIsolatedStorageFile(isoType);
            try
            {
                flag = isolatedStorageFile.GetDirectoryNames(directoryName).Length != 0;
            }
            catch
            {
                flag = false;
            }
            finally
            {
                isolatedStorageFile.Dispose();
            }
            return flag;
        }

        public static bool HasIsolatedFile(string fileName, IsolatedType isoType)
        {
            bool flag;
            if (string.IsNullOrEmpty(fileName))
            {
                return false;
            }
            IsolatedStorageFile isolatedStorageFile = GetIsolatedStorageFile(isoType);
            try
            {
                flag = isolatedStorageFile.GetFileNames(fileName).Length != 0;
            }
            catch
            {
                flag = false;
            }
            finally
            {
                isolatedStorageFile.Dispose();
            }
            return flag;
        }

        public DataSet Import(string fileName)
        {
            return Import(fileName, DataFileType.Auto);
        }

        public DataSet Import(string fileName, DataFileType dataFileType)
        {
            if (fileName == null)
            {
                throw new ArgumentNullException("fileName");
            }
            if (fileName.Length == 0)
            {
                throw new ArgumentException("fileName");
            }
            FileInfo info = new FileInfo(fileName);
            if (!info.Exists)
            {
                throw new FileNotFoundException();
            }
            if (dataFileType == DataFileType.Auto)
            {
                dataFileType = this.GetDataFileType(info.FullName);
            }
            switch (dataFileType)
            {
                case DataFileType.XML:
                    return this.ImportFromXML(info.FullName);

                case DataFileType.EXCEL:
                    return this.ImportFromExcel(info.FullName);

                case DataFileType.TEXT:
                    return this.ImportFromText(info.FullName, "\t");

                case DataFileType.CSV:
                    return this.ImportFromText(info.FullName, ",");
            }
            throw new NotSupportedException();
        }

        private DataSet ImportFromExcel(string fileName)
        {
            DataSet set = new DataSet();
            using (ExcelReader reader = new ExcelReader(fileName))
            {
                reader.Headers = true;
                reader.MixedData = false;
                reader.Open();
                try
                {
                    string[] sheetNames = reader.GetSheetNames();
                    for (int i = 0; i < sheetNames.Length; i++)
                    {
                        reader.SheetName = sheetNames[i];
                        DataTable table = null;
                        try
                        {
                            table = reader.ReadData();
                        }
                        catch (Exception ex)
                        {
                            table = null;
                        }
                        if (table != null)
                        {
                            set.Tables.Add(table);
                        }
                    }
                }
                finally
                {
                    reader.Close();
                }
            }
            return set;
        }

        private DataSet ImportFromText(string fileName, string separator)
        {
            StreamReader reader = null;
            Encoding encoding = TextHelper.GetEncoding(fileName);
            if (encoding == Encoding.UTF8)
            {
                reader = File.OpenText(fileName);
            }
            else
            {
                reader = new StreamReader(fileName, encoding);
            }

            DataTable table = new DataTable();
            using (reader)
            {
                string str = null;
                str = reader.ReadLine();
                if (str != null)
                {
                    string[] strArray = str.Split(new string[] { separator }, StringSplitOptions.None);
                    for (int i = 0; i < strArray.Length; i++)
                    {
                        if (strArray[i].Length != 0)
                        {
                            table.Columns.Add(strArray[i], typeof(string));
                        }
                        else
                        {
                            table.Columns.Add("COL_" + i.ToString("00"), typeof(string));
                        }
                    }
                    str = null;
                }
                while ((str = reader.ReadLine()) != null)
                {
                    string[] values = str.Split(new string[] { separator }, StringSplitOptions.None);
                    if (values.Length != 0)
                    {
                        table.Rows.Add(values);
                    }
                    str = null;
                }
            }
            table.AcceptChanges();
            DataSet set = new DataSet();
            set.Tables.Add(table);
            return set;
        }

        private DataSet ImportFromXML(string fileName)
        {
            DataSet set = new DataSet();
            set.ReadXml(fileName, XmlReadMode.Auto);
            return set;
        }

        public static void IsolatedCreateDirectory(string directoryName, IsolatedType isoType)
        {
            if (string.IsNullOrEmpty(directoryName))
            {
                throw new ArgumentException("directoryName");
            }
            IsolatedStorageFile isolatedStorageFile = GetIsolatedStorageFile(isoType);
            try
            {
                isolatedStorageFile.CreateDirectory(directoryName);
            }
            catch (Exception exception)
            {
                Trace.WriteLine(exception);
            }
            finally
            {
                isolatedStorageFile.Dispose();
            }
        }

        public static void IsolatedDeleteFile(string fileName, IsolatedType isoType)
        {
            if (!string.IsNullOrEmpty(fileName))
            {
                IsolatedStorageFile isolatedStorageFile = GetIsolatedStorageFile(isoType);
                try
                {
                    isolatedStorageFile.DeleteFile(fileName);
                }
                catch (Exception exception)
                {
                    Trace.WriteLine(exception);
                }
                finally
                {
                    isolatedStorageFile.Dispose();
                }
            }
        }

        public static object IsolatedExtractObject(string fileName, Type type, IsolatedType isoType)
        {
            object obj2 = null;
            try
            {
                using (IsolatedStorageFileStream stream = GetIsolatedStorageFileStream(fileName, FileMode.Open, isoType))
                {
                    obj2 = new XmlSerializer(type).Deserialize(stream);
                    stream.Close();
                }
            }
            catch (Exception exception)
            {
                Trace.WriteLine(exception);
                obj2 = Activator.CreateInstance(type, true);
            }
            return obj2;
        }

        public static void IsolatedStorageObject(string fileName, object obj, IsolatedType isoType)
        {
            try
            {
                using (IsolatedStorageFileStream stream = GetIsolatedStorageFileStream(fileName, FileMode.Create, isoType))
                {
                    new XmlSerializer(obj.GetType()).Serialize((Stream)stream, obj);
                    stream.Close();
                }
            }
            catch (Exception exception)
            {
                Trace.WriteLine(exception);
            }
        }


        public static string GetFileName(string fullPath)
        {
            string[] parts = fullPath.Split('\\');

            if (fullPath.Contains("//"))
            {
                parts = fullPath.Split('/');
            }

            return parts[parts.Length - 1];
        }

        public static string GetDirectory(string fullPath)
        {
            string fileName = GetFileName(fullPath);
            return fullPath.Replace("\\" + fileName, "");
        }

        //public static void Save(string path)
        //{
        //    string directory = GetDirectory(path);
        //    if (!Directory.Exists(directory))
        //    {
        //        Directory.CreateDirectory(directory);
        //    }
        //}



        private void WriteTextLine(StreamWriter sw, string s, bool ANSI)
        {
            if (ANSI)
            {
                byte[] bytes = Encoding.Unicode.GetBytes(s);
                sw.WriteLine(Encoding.Default.GetString(Encoding.Convert(Encoding.Unicode, Encoding.Default, bytes)));
            }
            else
            {
                sw.WriteLine(s);
            }
        }
    }
}
